package cn.openea.perpartner.meily.web.convert;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.openea.perpartner.meily.web.entity.*;
import cn.openea.perpartner.meily.web.entity.dto.SkuDataDto;
import cn.openea.perpartner.meily.web.mapper.ShopBaseSpecMapper;
import cn.openea.perpartner.meily.web.mapper.ShopBaseSpecValueMapper;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Weird077
 * @description TODO
 * @date 2023-04-23 17:31
 */
@Slf4j
@Component
public class SkuDataConvert {

    @Autowired
    private ShopBaseSpecMapper shopBaseSpecMapper;
    @Autowired
    private ShopBaseSpecValueMapper baseSpecValueMapper ;
    private final String PREFIX = "skus";

    public SkuDataDto toSkuDataList(JSONObject obj) {
        String productId = obj.getString("productId");
        JSONObject skuJSON = toSkuJSON(obj);
        Set<String> skuCodeSet = getSkuCodeSet(skuJSON);
        JSONArray skuArray = toSkuArray(skuJSON, skuCodeSet);
        List<ShopProductSku> skuList = new ArrayList<>();
        for (Object json : skuArray) {
            skuList.add(BeanUtil.toBean(json, ShopProductSku.class));
        }
        skuList.forEach(sku -> sku.setProductId(productId));
        Set<String> specIdSet = getSpecIdSet(skuCodeSet);
        List<ShopProductSpec> specList = toSpec(productId, specIdSet);
        List<ShopProductSpecValue> specValueList = toSpecValue(productId, specIdSet);
        return SkuDataDto.builder()
                .skuList(skuList)
                .specList(specList)
                .specValueList(specValueList)
                .build();
    }

    private List<ShopProductSpec> toSpec(String productId, Set<String> specIdSet) {
        List<ShopBaseSpec> baseSpecList = shopBaseSpecMapper.selectJoinList(ShopBaseSpec.class, new MPJLambdaWrapper<ShopBaseSpec>()
                .select(ShopBaseSpec::getMerchantId, ShopBaseSpec::getStatus,ShopBaseSpec::getCreateTime)
                .select(ShopBaseSpec::getId, ShopBaseSpec::getTitle, ShopBaseSpec::getSort)
                .leftJoin(ShopBaseSpecValue.class, ShopBaseSpecValue::getSpecId, ShopBaseSpec::getId)
                .in(ShopBaseSpecValue::getId, specIdSet).distinct());
        baseSpecList = baseSpecList.stream().sorted(Comparator.comparing(ShopBaseSpec::getCreateTime))
                .collect(Collectors.toList());

        List<ShopProductSpec> specList = new ArrayList<>();
        for (int i = 0; i < baseSpecList.size(); i++) {
            ShopProductSpec spec = ShopProductSpec.builder()
                    .productId(productId)
                    .merchantId(baseSpecList.get(i).getMerchantId())
                    .title(baseSpecList.get(i).getTitle())
                    .sort(i + 1)
                    .status(baseSpecList.get(i).getStatus())
                    .specId(Convert.toStr(baseSpecList.get(i).getId()))
                    .build();
            specList.add(spec);
        }
        return specList;
    }

    private List<ShopProductSpecValue> toSpecValue(String productId, Set<String> specIdSet) {
        List<ShopBaseSpecValue> baseSpecValueList = baseSpecValueMapper.selectList(Wrappers.<ShopBaseSpecValue>lambdaQuery()
                .in(ShopBaseSpecValue::getId, specIdSet));
        List<ShopProductSpecValue> specValueList = new ArrayList<>();
        baseSpecValueList.stream().forEach(baseSpecValue -> {
            ShopProductSpecValue specValue = ShopProductSpecValue.builder()
                    .productId(productId)
                    .merchantId(baseSpecValue.getMerchantId())
                    .title(baseSpecValue.getTitle())
                    .sort(baseSpecValue.getSort())
                    .status(baseSpecValue.getStatus())
                    .specId(Convert.toStr(baseSpecValue.getSpecId()))
                    .specValueId(Convert.toStr(baseSpecValue.getId()))
                    .build();
            specValueList.add(specValue);
        });
        return specValueList;
    }

    /**
     * 过滤数据，只保留sku数据
     *
     * @param obj
     * @return
     */
    private JSONObject toSkuJSON(JSONObject obj) {
        JSONObject json = new JSONObject();
        for (Map.Entry<String, Object> entry : obj.entrySet()) {
            if (entry.getKey().contains(PREFIX)) {
                json.put(entry.getKey(), entry.getValue());
            }
        }
        return json;
    }

    /**
     * sku数据分组
     *
     * @param obj
     * @return
     */
    private JSONArray toSkuArray(JSONObject obj, Set<String> skuCodeSet) {
        JSONArray array = new JSONArray();
        for (String skuCode : skuCodeSet) {
            JSONObject json = new JSONObject();
            for (Map.Entry<String, Object> entry : obj.entrySet()) {
                if (StrUtil.equals(skuCode, getSkuCode(entry.getKey()))) {
                    json.put(getKey(entry.getKey()), entry.getValue());
                }
            }
            json.put("data", skuCode);
            array.add(json);
        }
        return array;
    }

    private Set<String> getSkuCodeSet(JSONObject obj) {
        Set<String> set = new HashSet<>();
        for (Map.Entry<String, Object> entry : obj.entrySet()) {
            set.add(getSkuCode(entry.getKey()));
        }
        return set;
    }

    private Set<String> getSpecIdSet(Set<String> skuCodeSet) {
        Set<String> specIdSet = new HashSet<>();
        for (String skuCode : skuCodeSet) {
            String[] specIds = StrUtil.split(skuCode, "-");
            specIdSet.add(specIds[0]);
            specIdSet.add(specIds[1]);
        }
        return specIdSet;
    }

    private String getKey(String str) {
        return StrUtil.sub(str, str.lastIndexOf("[") + 1, str.lastIndexOf("]"));
    }

    private String getSkuCode(String str) {
        return StrUtil.sub(str, str.indexOf("[") + 1, str.indexOf("]"));
    }
}
